type t = (string, string) => string
type t = (~firstName: string, ~lastName: string) => string
type t = (~firstName: string=?, ~lastName: string=?) => string

type t = (string, string, superLongIdentifierHere, superLongIdentifierHere, superLongIdentifierHere) => okok

type t = (~firstName: string, ~lastName: string, ~long:  superLongIdentifierHere=?, ~long2: superLongIdentifierHere=?, ~long3: superLongIdentifierHere=?) => string


type t = (_, typeConstr<'a, state, 'foo>, 'x as 'y, module(S), %extension) => string

external c_binding: (string, string, superLongIdentifierHere, superLongIdentifierHere, superLongIdentifierHere) => okok = "c_binding_external_primitive"

external c_binding: (~any: _, string, ~firstClassModule: module(Hashmap with type key = string and type value = int and type superLongThingHere = definitelyLineBreak)=?, ~typeConstr: typeConstr<superLongIdentifierHere, superLongIdentifierHere, superLongIdentifierHere>, ~subArrow: (~subArrow: 'a1, ~subArrowParameter: 'a2, ~subArrowParameter3: loooooooongTypExpr) => (foo, bar, baz) ,~subArrow2: (~subArrow: 'a1, ~subArrowParameter: 'a2, ~subArrowParameter3: loooooooongTypExpr) => (foo, bar, baz, veryLooooooooooooooooongTupleTypeHere, veryLooooooooooooooooongTupleTypeHere, shoulBreakThatLine ), ~jsObject: {"name": string, "otherLongName": evenLongerType, "woooooooooooooo": excitingTypeHereBecauseItWillBreakthatLine}=?) => okok = "c_binding_external_primitive"

type t = (~firstName: string, ~lastName: string) => {
  "name": string,
  "age": int,
  "moreProps": superLongIdentifierHere,
  "moreProps2": superLongIdentifierHere2,
  "moreProps3": superLongIdentifierHere3,
  "moreProps4": superLongIdentifierHere4,
}

type t = (~firstName: string, ~lastName: string) => (
  name, string,
  age, int,
  moreProps, superLongIdentifierHere,
  moreProps2, superLongIdentifierHere2,
  moreProps3, superLongIdentifierHere3,
  moreProps4, superLongIdentifierHere4
)

type t = (~firstName: string, ~lastName: string) => typeConstr<
  name, string,
  age, int,
  moreProps, superLongIdentifierHere,
  moreProps2, superLongIdentifierHere2,
  moreProps3, superLongIdentifierHere3,
  moreProps4, superLongIdentifierHere4,
>

type t = (~firstName: string, ~lastName: string) =>
  module(Hashmap with type key = string and type value = int and type superLongThingHere = definitelyLineBreak)

type t = (@attr string, @attr float) => unit
type t = (@attr @attr2 string, @attr @attr2 float, @attr3 int) => unit

type t = @attr (string => unit)
type t = @attr (foo, bar, baz) => unit
type t = @attr (foo, @attr2 ~f:bar, @attr3 ~f:baz) => unit

type t = @attr (string => @attr (int => unit))
type t = @attr (string, int) => @attr (int, float) => unit
type t = @attr (int => @attr (int, float) => @attr (unit => unit => unit))
type t = @attr ((@attr2 ~f: int, @attr3  ~g: float) => unit)


type f = (@attr @attr @attr @attr @attr @attr @attr @attr @attr ~f: superLong, @attr2  @superLongAttributeNameSuperLongsuperLongAttributeName @attr2 @superLongAttributeNameSuperLongsuperLongAttributeName ~g: wowwwThisisLonggggg, @attr3 ~h: ccccrazysldkfjslkdjflksdjkf=?) => unit

type t = @attr (stringWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong => @attr2 (floatWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong => @attr3 (intWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong => unitWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong)))


type t = @attr (fooWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, barWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, bazWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => @attr2 (stringWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, floatWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => unit


type t = @attr @attrWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong @attrWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong (fooWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, barWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, bazWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => @attr2 @attrWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong @attrWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong (stringWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, floatWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => unit


external debounce: (int, unit) => unit = "debounce";

external debounce: int => (unit => unit) = "debounce";

external debounce: (int, (unit => unit)) => (unit => unit) = "debounce";

external debounce: (int, (unit => unit), (unit => unit)) => (unit => unit) = "debounce";

external debounce: (int, (unit => unit), ( unit => (unit => unit))) => (unit => unit) = "debounce";

type returnTyp = (int, int) => @magic float
type returnTyp = (intWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, intWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => @magic float
type returnTyp = (intWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong, intWithSuperLongIdentifierNameLoooooooooooooooooooooooooooooooooooooooooooooong) => @magic @magicWithSuperLongIdentiefierNameLoooooooooooooooooooooooong @magicWithSuperLongIdentiefierNameLoooooooooooooooooooooooong float

// uncurried
type t = (. int) => int
type t = (. int, int) => int
type t = (. int, . int) => int
type t = (. int, int, . int, int) => int


type t = (. @attr int) => unit 
type t = (. @attr int, . @attr2 int) => unit 
type t = (. @attrOnInt int, @attrOnInt int, . @attrOnInt int, @attrOnInt int) => int
type t = (. @attr ~x: int, ~y: int, . @attr ~z: int, @attr ~omega: int) => unit 

@val external requestAnimationFrame: (float => unit) => unit = "requestAnimationFrame"
@val external requestAnimationFrame: @attr (float => unit) => unit = "requestAnimationFrame"

type arrows = (int, (float => unit) => unit, float) => unit

// tuple as single parameter
let prepare_expansion: ((type_expr, type_expr)) => (type_expr, type_expr) = f

type getInitialPropsFn<'a> = {
  "query": dict<string>,
  "req": Js.Nullable.t<Js.t<'a>>,
} => Js.Promise.t<Js.t<'a>>

// keep parens
external fromPoly: ([> ] as 'a) => t = "%identity"

external fromPoly: ([> ] as 'a, [> ] as 'b) => t = "%identity"
